package com.bkgy.util;

import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;

public class SignUtil {

    public static void main(String[] args) {
        // 1. 待签名的字符串
        String plaintext = "202512040903:SLAF0001:SLZNGC:BGMMS";

        // 2. 16进制私钥字符串（替换为你的实际私钥）
        String privateKeyHex = "3082014a0201003082012b06072a8648ce3804013082011e02818100f619c1c5b3f0a73d3942497a08dc6b0ae710fe1cc4d23ca79d10b06f11f308e0d2c9f3a46480b7b304198c9e63f917127275b82d67a77c4ea210c475abce1b3c2faaf7b130806d20e0e894da933d2f3afb1f0e54101d1280336b2cb5f616c855811bcd8f0a51f26bb30bc1ee2f09255dba0b4cc5fea7f9c9ca1ce716f6bc393d021500c89b0e60e6abd5e96ae5b475a2b622a7d51e469b0281807f3c2ddc7b220bd3fb0916573c09c848ad7b5bf576d21bca6fdcf55978ee3f8371bdf9f08e0c8b07c9736af466d60c0b4cd82cf3a3510b7cf3eb14c3ba88d466cd6953b0c7bfbd6a604311e0b3d43a5a1f9bef11da5effdefeb07496ed6cc8f6021494e5b162850da827fca3a74d7572be97a777dfdd21d4859690c1b6beee000416021441cfb5e8208ad687f268868ccf8499e10fe37a12";
        //String publicKeyHex = "308201b73082012b06072a8648ce3804013082011e02818100f619c1c5b3f0a73d3942497a08dc6b0ae710fe1cc4d23ca79d10b06f11f308e0d2c9f3a46480b7b304198c9e63f917127275b82d67a77c4ea210c475abce1b3c2faaf7b130806d20e0e894da933d2f3afb1f0e54101d1280336b2cb5f616c855811bcd8f0a51f26bb30bc1ee2f09255dba0b4cc5fea7f9c9ca1ce716f6bc393d021500c89b0e60e6abd5e96ae5b475a2b622a7d51e469b0281807f3c2ddc7b220bd3fb0916573c09c848ad7b5bf576d21bca6fdcf55978ee3f8371bdf9f08e0c8b07c9736af466d60c0b4cd82cf3a3510b7cf3eb14c3ba88d466cd6953b0c7bfbd6a604311e0b3d43a5a1f9bef11da5effdefeb07496ed6cc8f6021494e5b162850da827fca3a74d7572be97a777dfdd21d4859690c1b6beee000381850002818100e2a73f66e32720a64e71df143698edf3a87b16509914099078ea39ef86b40da5a5c8e704a68d8b6ddbf762730d5c04eb49e5e35d049ab394bd3789fd49d6214488f2d50f2266640000aa5000dea3ed7a7eda23cbd08d05645c0d07f723e5c55db5027cbceaa1bb713f6e93825a0969fae873563a869f1a725288160560d63de2";

        // 3. 使用私钥签名
        String signatureHex = signWithHexPrivateKey(plaintext, privateKeyHex);

        System.out.println("签名结果（16进制）：" + signatureHex);
    }

    /**
     * 16进制字符串转字节数组
     */
    private static byte[] hexToBytes(String hex) {
        if (hex == null || hex.length() % 2 != 0) {
            throw new IllegalArgumentException("无效的16进制字符串（长度必须为偶数）");
        }
        int len = hex.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 每两个字符转换为一个字节（16进制高位左移4位 + 低位）
            bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return bytes;
    }

    /**
     * 字节数组转16进制字符串（方便签名结果展示/存储）
     */
    private static String bytesToHex(byte[] bytes) {
        if (bytes == null) return null;
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            // 转换为两位16进制字符（补0）
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * 使用16进制私钥对字符串进行签名
     *
     * @param plaintext     待签名的字符串
     * @param privateKeyHex 16进制私钥字符串（PKCS#8编码格式）
     * @return 签名结果（16进制字符串），失败返回null
     */
    public static String signWithHexPrivateKey(String plaintext, String privateKeyHex) {
        try {
            // 步骤1：16进制私钥 → 字节数组
            byte[] privateKeyBytes = hexToBytes(privateKeyHex);

            // 步骤2：字节数组 → PrivateKey对象（DSA私钥用PKCS#8规范）
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("DSA"); // 指定算法为DSA
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

            // 步骤3：初始化签名工具，用私钥签名
            Signature signature = Signature.getInstance("DSA"); // 签名算法为DSA
            signature.initSign(privateKey); // 用私钥初始化签名

            // 步骤4：更新待签名的数据（字符串转字节数组，指定UTF-8编码避免乱码）
            signature.update(plaintext.getBytes(StandardCharsets.UTF_8));

            // 步骤5：生成签名（字节数组）
            byte[] signatureBytes = signature.sign();

            // 步骤6：签名字节数组 → 16进制字符串（方便使用）
            return bytesToHex(signatureBytes);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}